home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / os2 / srefv12i.zip / ssicache.rxx < prev    next >
Text File  |  1997-01-09  |  17KB  |  504 lines

  1. s/* The ssi-caching thread, for SRE-FILTER.
  2. Uses workdata_temp for storage
  3.   call with queue containing:
  4.  transaction ' ' host_nickname ',' newq ',' newsem ','  filename
  5.  
  6.   returns
  7.      status ' ' filename
  8.  
  9. status=0 : no match
  10.       1  : use filename as is 
  11.       2  : read filename, and continue to do ssi's 
  12. */
  13.  
  14. parse upper arg storage_dir,  usequeue , USESEM, max_semwait,port,cache_size,def_duration,def_trigtype
  15.  
  16. storage_dir=strip(storage_dir,'t','\')
  17. cache_list.0=0          ; cache_list.!size=0 ; cache_list.!marked=0
  18. max_marked=8   /* cleanup after this many expirations, etc. */
  19.  
  20. call pmprintf(' SRE-FILTER ssi-cache thread: ssi_cache dir='||storage_dir)
  21.  
  22.  
  23. mytid=dostid()
  24. call pmprintf(' SRE-FILTER ssi-cache thread: queue='||usequeue)
  25. call pmprintf(' SRE-FILTER ssi-cache thread: semaphore='||usesem)
  26. call pmprintf(' SRE-FILTER ssi-cache thread: thread id ='||mytid)
  27.  
  28. if storage_dir="" | usequeue="" | USESEM="" then do
  29.    call pmprintf('SRE-FILTER ssi-cache thread: initialization ERROR: '||usequeue)
  30.    exit
  31. end
  32.  
  33. /* clear junk from cache storage directory */
  34. oo=sysfiletree(storage_dir||'\_CSH*.'||port,oofs,'FO')
  35. do mm=1 to oofs.0
  36.   foo=sysfiledelete(oofs.mm)
  37. end
  38. call pmprintf(' SRE-Filter ssi-cache thread: Deleted 'oofs.0' old cache files')
  39. drop oofs.
  40.  
  41. /* Initialization now done == start waiting for requests for ssi-cache */
  42.  
  43. signal on error name iserror
  44. signal on syntax name iserror
  45. idid=0
  46.  
  47. bakme:
  48.  a=rxqueue('s',usequeue)
  49.  aq=queued()
  50.  if aq=0 then do
  51.     WOW=EVENTSEM_WAIT(USESEM,max_semwait)
  52.     aq=-1
  53.     if wow=640 then do
  54.          signal bakme
  55.     end
  56.     IF WOW<>0 THEN do         /* FATAL ERROR */
  57.         call pmprintf(' SRE-Filter ssi-cache Thread: fatal semaphore error: 'wow)
  58.         EXIT
  59.     end
  60.  end
  61.  wow=EVENTSEM_RESET(usesem)
  62.  
  63.  if aq=-1 then
  64.    if queued()=0 then signal bakme
  65.  PARSE pull isit0
  66.  
  67.  
  68.  isit0=translate(isit0,' ','000d0a09'x)
  69.  
  70.  if isit0=" " then signal bakme
  71.  
  72. /* die command? */
  73.  if abbrev(isit0,'*DIE*')=1 then
  74.           exit
  75.  
  76. goobs:
  77.   parse var isit0  idnum   ',' newq ',' newsem ','  anfile addto
  78.   addto=strip(addto);anfile=strip(anfile) ; 
  79.   parse var idnum idnum host_nickname
  80.   host_nickname=strip(upper(host_nickname))
  81.   if newq="" | newsem="" then do
  82.         call pmprintf(' SRE-FILTER ssi-cache thread: missing queue or semaphore ')
  83.         exit
  84.   end
  85.   newq=upper(strip(newq)); newsem=upper(strip(newsem))
  86. anfile=upper(strip(anfile))
  87. /* do something ... */
  88.   select
  89.     when abbrev(anfile,'*RESET')=1 then do
  90.           do mm=1 to cache_list.0
  91.              foo=sysfiledelete(cache_list.mm.!dafile)
  92.           end
  93.           foo=cache_list.0
  94.           foo2=cache_list.!size
  95.           drop cache_list.
  96.           cache_list.0=0 ; cache_list.!size=0 ; cache_list.!marked=0
  97.           call lineout addto,' SRE-Filter ssi-cache: cleared ' foo2 ' bytes in ' foo ' files in:' storage_dir
  98.           call lineout addto
  99.           a=rxqueue('s',newq)
  100.           push idnum ','  1
  101.           wow=eventsem_post(newsem)
  102.     end
  103.  
  104.     when abbrev(anfile,'*STATUS')=1 then do
  105.         foo=do_status(anfile)
  106.        a=rxqueue('s',newq)
  107.         push idnum ','  1
  108.         wow=eventsem_post(newsem)
  109.     end
  110.  
  111.     when abbrev(anfile,'*CLEANUP')=1 then do
  112.        foo=shrink_cache(1,addto)
  113.        a=rxqueue('s',newq)
  114.        push idnum ','  1
  115.        wow=eventsem_post(newsem)
  116.     end
  117.  
  118. /* get rid of old entries? */
  119.    when abbrev(anfile,'*REMOVE')=1 then do
  120.       removes=substr(anfile,8)
  121.       removes=translate(removes,' ','+='||'000d0a'x)
  122.       removes=packur(removes); removes=upper(translate(removes,'\','/'))
  123.  
  124.       do mm=1 to words(removes)
  125.           arem=strip(word(removes,mm))
  126.           call lineout addto,' Attempting to remove from SSI-cache: ' arem
  127.           do meow=1 to cache_list.0
  128.             if cache_list.meow=arem & cache_list.meow.!host=host_nickname then do
  129.                 wass=cache_list.meow.!size
  130.                 foo=cache_del(meow)
  131.                 call lineout addto,'    ....  removed ' arem '( ' wass ' bytes) from SSI-cache '
  132.             end
  133.           end
  134.           call lineout addto
  135.           a=rxqueue('s',newq)
  136.           push idnum ','  1
  137.           wow=eventsem_post(newsem)
  138.       end
  139.  
  140.     end
  141.  
  142.     otherwise do                      /* look up a cache entry!!!!!!! */
  143.       a=rxqueue('s',newq)
  144.       dog1=get_from_ssi_cache(anfile,addto)
  145.  
  146.       if addto=' ' then do
  147.           push idnum ',' dog1
  148.           wow=eventsem_post(newsem)
  149.       end               /* if ADD, no return expected */
  150.     end                 /* otherwiase */
  151.  
  152.   end          /* selekct */
  153. signal bakme
  154.  
  155.  
  156. iserror:
  157. signal off error ; signal off syntax
  158. foo=condition('d')
  159. call pmprintf(' SRE-FIlter: error in ssi-cache thread 'foo)
  160.  
  161. n1=queued()
  162. a=rxqueue('d',usequeue)
  163. a=rxqueue('c',usequeue)
  164. foo=eventsem_reset(usesem)
  165. a=eventsem_close(usesem)
  166. a=eventsem_create(usesem)
  167. a=rxqueue('s',newq)
  168. push idnum ', 0 '
  169. wow=eventsem_post(newsem)
  170. call pmprintf('SRE-Filter: done resetting ssi-cache thread ')
  171. signal on error name iserror
  172. signal on syntax name iserror
  173. signal bakme
  174.  
  175. exit
  176.  
  177. /***********/
  178. /* anfile = file to be looked for
  179.    dafile = a "temporary" file used that should be stored in the cache
  180.  
  181. fields of cache_list.
  182.    .0 = # entries
  183.    .!size= Running totals: kbytes
  184.    .!marked= Marked for deletion
  185.    .m = name of file "to be cached" (anfile) -- or =0 if marked for deletion
  186.    .m.!type = type of file (1=use as is, 2=process further)
  187.    .m.!time = time file was created
  188.    .m.!host= host nickname for this entry
  189.    .m.!recent = most recent access
  190.    .m.!size = size of Cached-file (the _CSH*.80 file)
  191.    .m.!duration = lifespan of this file
  192.    .m.!ntriggers   = # of trigger files (usually =1 : own file name )
  193.    .m.!trigger.n = A trigger file stamp: date size attribs fully_qualified_name
  194.    .m.!trigtype  = Type of trigger (DATE TIME TIMEDATE DATETIME SIZE ALL)
  195.    .m.!dafile = The "cached" (_CSH*.80) file
  196. */
  197.  
  198. get_from_ssi_cache:procedure expose cache_list. storage_dir def_duration cache_size def_trigtype ,
  199.                 host_nickname max_marked
  200.  
  201. parse upper arg anfile,todo
  202. inc=cache_list.0
  203. nowtime=date('b')+(time('m')/(24*60))
  204.  
  205. /* ========  Here to add a file to the cache */
  206. if todo<>' ' then do
  207.    itype=2         /* assume changes will be necessary */
  208.    parse var todo dafile al
  209.    dafile=strip(dafile)
  210.    triggers=anfile 
  211.    duration=def_duration ; trigtype=def_trigtype
  212.    do until al=""
  213.         parse var al val ';' al
  214.         val=upper(strip(val)) 
  215.         val1=strip(word(val,1))
  216.         if val="ASIS" then do   /* asis must be explicitly invoked by CACHE ASIS */
  217.                 itype=1
  218.         end
  219.         if val="NOCHANGE" then itype=1  /* no change occurs if all static ssis */
  220.         if val1="TRIGGER" then  triggers=triggers||' '||subword(val,2)
  221.         if val1="TRIGGER_TYPE" then  trigtype=strip(word(val,2))
  222.         if val1="DURATION" | val1="DAYS" then  duration=strip(word(val,2))
  223.         if val1="HOURS" then  do
  224.             duration=word(val,2)
  225.             if datatype(duration)="NUM" then duration=duration/24 ;
  226.          end
  227.    end
  228.  
  229. /* done with file specific options */
  230.    if datatype(duration)<>'NUM' then duration=def_duration
  231.  
  232. /* NOte:itype=1 means "return as is"*/
  233.  
  234.    dafilesize=chars(dafile); foo=stream(dafile,'c','close')
  235.    if dafilesize=0 then return 0  /* no such entry */
  236.    if dafilesize>(cache_size*500) then do
  237.      foo=sysfiledelete(dafile)
  238.      return ' '  /* too big */
  239.    end
  240. /* size is not a problem,save results */
  241.    inc=inc+1
  242.    cache_list.inc=anfile
  243.    cache_list.inc.!host=host_nickname
  244.    cache_list.inc.!type=itype                       /* 1= use as is */
  245.    cache_list.inc.!ntriggers=0
  246.    cache_list.inc.!duration=duration
  247.    cache_list.inc.!time=nowtime          /*the creation time stamp */
  248.    cache_list.inc.!recent=nowtime        /* the most recent hit time stamp */
  249.    cache_list.inc.!trigtype=trigtype   /* type of trigger */
  250.  
  251.   do until triggers=""                  /* add triggers (possibly just self */
  252.         parse upper var triggers atrig triggers ; atrig=strip(atrig)
  253.         foo=sysfiletree(atrig,stamp,'FT')
  254.         if stamp.0>0 then do
  255.            lk=cache_list.inc.!ntriggers+1
  256.            cache_list.inc.!trigger.lk=space(stamp.1)
  257.            cache_list.inc.!ntriggers=lk
  258.         end
  259.    end
  260.    cache_list.inc.!dafile=dafile
  261.    cache_list.inc.!size=dafilesize
  262.    cache_list.!size=cache_list.!size+dafilesize
  263.    cache_list.0=inc
  264. /* get rid of old entries? */
  265.   do meow=1 to inc-1
  266.         if cache_list.meow=anfile & cache_list.meow.!host=host_nickname then do
  267.             foo=cache_del(meow)
  268.             leave
  269.         end
  270.   end
  271. /* now check size of cache, and delete files if necessary */
  272.    if cache_list.!size>(cache_size*1000) then
  273.          foo=shrink_cache(0)
  274.  
  275.    return ' '           /* no return info expected */
  276. end
  277.  
  278.  
  279. /*  ========== here to check for a file in the cache */
  280. do mm=1 to inc
  281.    if cache_list.mm=0 then iterate
  282.    if cache_list.mm=anfile  & cache_list.mm.!host=host_nickname then do    /* got a match -- check it's time and triggers */
  283.  
  284.         cache_list.inc.!recent=nowtime
  285.         fexpire=cache_list.mm.!time+cache_list.mm.!duration
  286.         if fexpire<nowtime then do           /* expired -- so no matdh */
  287.            foo=cache_del(mm)
  288.            return 0
  289.         end
  290.         do it0=1 to cache_list.mm.!ntriggers  /* check all trigger files */
  291.              atrig=cache_list.mm.!trigger.it0
  292.              atrig=strip(word(atrig,4))
  293.              foo=sysfiletree(atrig,nowstamp,'FT')
  294.              oldstamp=cache_list.mm.!trigger.it0
  295.              if nowstamp.0=0  then do
  296.                  Call pmprintf(" ERROR: ssi-cache trigger missing : " atrig)
  297.                  foo=cache_del(mm);  return 0
  298.              end
  299.              if CHECK_STAMP(nowstamp.1,oldstamp,cache_list.mm.!TRIGTYPE)=0 then do
  300.                  foo=cache_del(mm);  return 0
  301.              end
  302.         end 
  303. /* not expired, triggers okay; so use it */
  304. /*   call pmprintf(" ssi-cache, match: " mm' 'cache_list.mm.!type' 'cache_list.mm.!dafile)*/
  305.  
  306. /* last check -- make sure size is correct */
  307.         tst1=chars(cache_list.mm.!dafile); foo=stream(cache_list.mm.!dafile,'c','close')
  308.         if tst1<>cache_list.mm.!size then do
  309.             call pmprintf(' SSI-cache error: mismatch in cache sizes 'tst1 ',' cache_list.mm.!size', 'cache_list.mm.!dafile)
  310.             foo=cache_del(mm)  /* delete this entry */
  311.             return 0
  312.         end
  313.         itype=cache_list.mm.!type
  314.         return itype' 'cache_list.mm.!dafile
  315.    end
  316. end
  317. return 0                /* don't got */
  318.  
  319. /*********/
  320. check_stamp:procedure
  321. parse upper arg stmp1,stmp2,atype
  322.  
  323. select
  324.   when atype='SIZE' then do
  325.     stmp1=strip(word(stmp1,2))
  326.     stmp2=strip(word(stmp2,2))
  327.   end
  328.   when atype='TIMEDATE' | atype='DATETIME' then do
  329.     stmp1=strip(word(stmp1,1))
  330.     stmp2=strip(word(stmp2,1))
  331.  
  332.   end
  333.   when atype="ALL" then do
  334.     stmp1=strip(space(stmp1))
  335.     stmp2=strip(space(stmp2))
  336.   end
  337.   when atype='TIME' then do
  338.     stmp1=substr(strip(stmp1),10,5)
  339.     stmp2=substr(strip(stmp2),10,5)
  340.   end
  341.   when atype='DATE' then do
  342.     stmp1=substr(strip(stmp1),1,8)
  343.     stmp2=substr(strip(stmp2),1,8)
  344.   end
  345.   otherwise do
  346.      call pmprintf(' bad trigtype: 'atype)
  347.      return 0           /* should never happen */
  348.   end
  349. end
  350.  
  351. /*call pmprintf(stmp1' !! 'stmp2) */
  352. if stmp1=stmp2 then return 1   /* 1 means "okay", 0 means "out of sync */
  353. return 0
  354.  
  355.  
  356.  
  357.  
  358. /*********/
  359. /* remove a cache entry */
  360. cache_del:procedure expose cache_list. cache_size max_marked
  361. parse arg nn
  362.   i1=cache_list.0
  363.   foo=sysfiledelete(strip(cache_list.nn.!dafile))
  364.   gsize=cache_list.nn.!size
  365.   cache_list.nn=0
  366.   cache_list.!size=cache_list.!size-gsize
  367. /*  call pmprintf(' deleted entry  #' nn ', cache size now = ' cache_list.!size)*/
  368.   cache_list.!marked=cache_list.!marked+1
  369.  
  370.   if cache_list.!marked > max_marked then foo=shrink_cache(0)
  371.  
  372.   return foo
  373.  
  374. /*******/
  375. do_status:procedure expose cache_list.  addto host_nickname /* display current state */
  376. parse arg iss0
  377. iss=translate(iss0,' ','*+=?')
  378.  
  379.  select 
  380.     when strip(upper(word(iss,2)))='SHORT' then do
  381.         call lineout addto,"  "
  382.         call lineout addto," Current status of SSI-Cache "
  383.         call lineout addto,' # entries ' cache_list.0 ', bytes stored = ' cache_list.!size
  384.         if cache_list.0>0 then do
  385.           call lineout addto,' Host-nickname : File    Cache-file , size   #trigger_files  most_recent_hit '
  386.           do mm=1 to cache_list.0
  387.             if cache_list.mm=0 then
  388.                 call lineout addto,' Entry ' mm ' marked for deletion '
  389.             else
  390.                 call lineout addto,cache_list.mm.!host ' : ' cache_list.mm ' ' ,
  391.                  filespec('n',cache_list.mm.!dafile) ', ' cache_list.mm.!size ' ' cache_list.mm.!ntriggers '  ' cache_list.mm.!time
  392.          end
  393.        end              /* clist>0 */
  394.     end
  395.     when words(iss)>1 then do
  396.       removes=substr(iss0,8)
  397.       removes=translate(removes,' ','+='||'000d0a'x)
  398.       removes=packur(removes); removes=upper(translate(removes,'\','/'))
  399.       removes=strip(word(removes,1))
  400.       call lineout addto,' '
  401.       call lineout addto,' Status info for cache entry: ' removes
  402.       do mm = 1 to cache_list.0
  403.         if cache_list.mm=removes & cache_list.mm.!Host=host_nickname then do
  404.            booger=cvtails(cache_list.mm.,stuff)
  405.            foo=arraysort(stuff)
  406.            do mm2=1 to stuff.0
  407.               aa=stuff.mm2
  408.               wow=cache_list.mm.aa
  409.               call lineout addto,'   ' aa ' = 'wow
  410.            end
  411.            leave
  412.         end             /* if */
  413.      end  /* do loop */
  414.  
  415.     end    /* when words iss */
  416.  
  417.     otherwise do                        /* show all the status stuff */
  418.        booger=cvtails(cache_list,stuff)
  419.        foo=arraysort(stuff)
  420.        do mm=1 to stuff.0
  421.             aa=stuff.mm
  422.             wow=cache_list.aa
  423.             call lineout addto,'   ' aa ' = 'wow
  424.        end
  425.    end
  426.  
  427. end
  428. call lineout addto
  429. return 0
  430.  
  431. /*********/
  432. /* shrink the cache 
  433.   get rid of "marked for deletions". ALso, cut size of cache to 85% of max */
  434.  
  435. shrink_cache:procedure expose cache_list. cache_size
  436. parse arg iwrite,tempfile
  437.  
  438. signal on error name aprob
  439. signal on syntax name prob
  440.  
  441. ntmp=0
  442.  
  443. if cache_list.0=0 then do
  444.    call lineout tempfile,' '
  445.    call lineout tempfile,' SSI-Cache cleanup: No entries in cache list '
  446.    call lineout tempfile
  447.    return 1
  448. end
  449.  
  450. wassize=cache_list.!size
  451. wasentries=cache_list.0
  452. nolds=0
  453. ncleaned=0
  454. /* This section is used to cut cache down to size */
  455. if cache_list.!size>(cache_size*1000) then do
  456.       iwas=cache_list.!size
  457.       iww=0
  458.       do iw=1 to cache_list.0           /* make a sortable list */
  459.           if cache_list.iw<>0 then do
  460.              iww=iww+1
  461.              sht.iww=left(cache_list.iw.!recent,15)||' '||iw||' '||cache_list.iw.!size||' '||cache_list.iw
  462.           end
  463.       end
  464.       sht.0=iww
  465.       foo=arraysort(sht,1,,1,15,'A','N')
  466. /* cut size of cache (by marking oldest for deletion, and deleting the cache file */
  467.       do iat=1 to sht.0
  468.             if cache_list.!size<(cache_size*850) then leave  /*clean out some extra */
  469.             parse var sht.iat tt nth asize aname ; nth=strip(nth) ;asize=strip(asize)
  470.             cache_list.!size=cache_list.!size-asize
  471.             dafile=strip(dafile); foo=sysfiledelete(cache_list.nth.!dafile)
  472.             cache_list.nth=0   /* mark for deletion, along with prior marked items */
  473.       end
  474.       ntmp=0
  475. end
  476. /* now shrink cache_list array  (remove marked for dletion enetries */
  477.  do iu=1 to cache_list.0
  478.          if cache_list.iu=0 then iterate 
  479.          ntmp=ntmp+1
  480.          tmps.ntmp=cache_list.iu
  481.          foo=cvcopy(cache_list.iu.,tmps.ntmp.)
  482.  end
  483.  tmps.0=ntmp
  484.  tmps.!size=cache_list.!size
  485.  tmps.!marked=0
  486.  drop cache_list.
  487.  foo=cvcopy(tmps,cache_list)
  488.  drop tmps.; drop sht.
  489.  if iwrite=1 then do
  490.    call lineout tempfile,' '
  491.    call lineout tempfile,' SSI-Cache cleanup: Starting size (entries,bytes): 'wasentries ',' wassize
  492.    call lineout tempfile,'                      ending size (entries,bytes): 'cache_list.0 ',' cache_list.!size
  493.    call lineout tempfile
  494.  end
  495.  
  496.  return 1
  497.  
  498. aprob:
  499. signal off syntax
  500. signal off error
  501. call pmprintf(' Some kind of error in SSICACHE:cleanup procedure')
  502. return 0
  503.  
  504.